package it.poste.il.compensatore.control.impl;


import org.apache.log4j.Logger;

import it.poste.il.compensatore.control.Integration;
import it.poste.il.compensatore.datamanager.DataManager;
import it.poste.il.compensatore.entities.Message;
import it.poste.il.compensatore.entities.MessageBody;
import it.poste.il.compensatore.entities.MessageStatus;
import it.poste.il.compensatore.entities.Operation;
import it.poste.il.compensatore.entities.SDPRequest;
import it.poste.il.compensatore.exceptions.compensatorExceptions.CompensatorTimeOutException;
import it.poste.il.compensatore.exceptions.compensatorExceptions.CompensatorIOException;
import it.poste.il.compensatore.utilities.LogFactory;
import it.poste.il.compensatore.utilities.LoggerCompensatore;
import it.poste.il.compensatore.utilities.SendSOAPMessage;

public class IntegrationImpl implements Integration {

	String response;
	private LogFactory loggerF;
	
	private Message message = new Message();
	private MessageBody messageBody =new MessageBody();
	private DataManager dataManager;
	private SendSOAPMessage sendSOAPMessage;
	private SDPRequest sdpRequest = new SDPRequest();
	
	public LogFactory getLoggerF() {
		return loggerF;
	}

	public void setLoggerF(LogFactory loggerF) {
		this.loggerF = loggerF;
	}

	public DataManager getDataManager() {
		return dataManager;
	}

	public void setDataManager(DataManager dataManager) {
		this.dataManager = dataManager;
	}

	
	public SendSOAPMessage getSendSOAPMessage() {
		return sendSOAPMessage;
	}

	public void setSendSOAPMessage(SendSOAPMessage sendSOAPMessage) {
		this.sendSOAPMessage = sendSOAPMessage;
	}

	public IntegrationImpl(){
		
	}
	
	/**
	 * Metodo syncMsg.
	 * Effettua la lettura del messaggio ricevuto in input, estrazione della requestId, 
	 * memorizzazione del messaggio, verifica per un eventuale annullamento o riallineamento
	 * ed invio all'ESB.
	 * @param messaggio ricevuto in input da SDP
	 * @return risposta dell'ESB;
	 * @throws Exception 
	 */
	public String syncMsg(String msg) throws Exception {
				
		String response = null;
		
		int fromAccountingDate = 0;
		int fromBranch = 8;
		int fromWorkingStationId = 13;
		int fromNumberOperationPdl = 17;
		int fromCounter = 23;
		String fase = "";
		Logger logger=loggerF.getLogger(this);
		//Estrazione della requestId dall'header
		logger.info("START PARSER");
		int startRequestID = msg.indexOf("requestID>");
		int endRequestID = msg.substring(startRequestID+10).indexOf("</");
		String requestId = msg.substring(startRequestID+10).substring(0,endRequestID);
		System.out.println("Request ID: " + requestId);
		logger.info("END PARSER");
		
		//lettura requestId
		
		logger.info("request id: " + requestId);

		sdpRequest.setAccountingDate(requestId.subSequence(fromAccountingDate, fromBranch).toString());
		logger.info(sdpRequest.getAccountingDate());
		sdpRequest.setBranch(requestId.substring(fromBranch, fromWorkingStationId));
		logger.info(sdpRequest.getBranch());
		sdpRequest.setWorkingStationId(Integer.parseInt(requestId.substring(fromWorkingStationId, fromNumberOperationPdl)));
		logger.info((""+sdpRequest.getWorkingStationId()));
		sdpRequest.setNumberOperationPdl(Integer.parseInt(requestId.substring(fromNumberOperationPdl, fromCounter)));
		logger.info(""+sdpRequest.getNumberOperationPdl());
		sdpRequest.setCounter(Integer.parseInt(requestId.substring(fromCounter, requestId.length()-1)));
		logger.info(""+sdpRequest.getCounter());
		fase=requestId.substring(requestId.length()-1);
		logger.info(fase);
		
		logger.info("request id: avccountingdate: " + sdpRequest.getAccountingDate() + " branch: " + sdpRequest.getBranch() + 
				" workingstation: " + sdpRequest.getWorkingStationId() + " counter: " + sdpRequest.getCounter() +
				" pdl: " + sdpRequest.getNumberOperationPdl());
		
		//memo
		logger.info("memorizza request");
		messageBody = dataManager.storeMsg(msg,sdpRequest);
		message = messageBody.getMessage();
		
		String verifica = dataManager.verifyRequest(message.getSdpRequestId(), fase);
		logger.info("esito verifica " + verifica);
		
		//verifica
		if(verifica.equals("R")){
			logger.info("verifica = 3 riallineamento");
			riallineamento();
		} else if(!verifica.equals("0")){
			logger.info("verifica annullamento");
			//verifica contiente l'id del messaggio da annullare sulla sdprequest
			annullamento(verifica);
		}
		try{
			response = invio(messageBody);
		} catch (CompensatorTimeOutException e) {
			logger.info("send avoid message for timeout");
			annullamento(messageBody.getMessage().getSdpRequestId().getId().toString());
		} catch (CompensatorIOException e){
			logger.error("Error send http request to ESB " + e);
			//da gestire la response
			throw e;
		}
		return response;
		
	}
	
	/**
	 * Metodo annullamento.
	 * Crea e invia il messaggio di annullamento.
	 * @return null;
	 */
//	public void annullamento(SDPRequest sdpRequest){
	public void annullamento(String sdpRequestId){
		Message avoidMessage = new Message();
		Logger logger=loggerF.getLogger(this);
		logger.info("metodo annullamento");

//		MessageBody avoidMessageBody = dm.
		
		//timeout
		//crea messaggio di anullamento
		//memorizza
//		**********************************************************
//		avoidMessage = dm.storeMsg(avoidMessage, requestId);
		//aggiorna stato messaggio annullato
	}
	
	/**
	 * Metodo riallineamento.
	 * Effettua le operazioni di riallinemanto.
	 * @return null;
	 */
	public void riallineamento(){
		Logger logger=loggerF.getLogger(this);
		logger.info("Riallineamneto al counter :" + sdpRequest.getCounter() + " per accountigdate "+
				sdpRequest.getAccountingDate() + " branch " + sdpRequest.getBranch() + " PDL " + sdpRequest.getNumberOperationPdl() +
				" workingStationId " + sdpRequest.getWorkingStationId());
	}
	
	/**
	 * Metodo invio.
	 * Invia il messaggio all'ESB e restitusce la risposta ricevuta oppure un messaggio di errore.
	 * @return response;
	 * @throws CompensatorTimeOutException 
	 * @throws CompensatorIOException 
	 */
	public String invio(MessageBody msgBody) throws CompensatorTimeOutException, CompensatorIOException{
		
		//*******************************************
		//manca la personalizzazione della request id
		Logger logger=loggerF.getLogger(this);
		logger.info("inzio metodo invio");
		String URL = msgBody.getMessage().getOperationId().getUrlEndpoint();
		logger.info("inzio metodo invio 2");
		String action = msgBody.getMessage().getOperationId().getOperationName();
		logger.info("inzio metodo invio 3");
		String msg = msgBody.getInputMessage();
		logger.info("inzio metodo invio 4");
		
		
		String result="";
		try {
			//Cambio di stato in "In attesa di risposta"
			logger.info("Cambio di stato in In attesa di risposta");
			dataManager.changeStatus(message, 1001L);
			logger.info("stato cambiato");
			logger.info("Invio request all'ESB");			
			int timeout = 1000;
			result = sendSOAPMessage.sendStringRequest(msg, URL, action, timeout);
		} catch (CompensatorTimeOutException e) {
			//Cambio di stato in "Errore..."
			logger.info("Errore timeout");
//			dataManager.changeStatus(message, 1004L);
//			logger.info("Stato cambiato");
//			result=e;
			throw e;
		} catch (CompensatorIOException e) {
			throw e;
		}
		
		return result;
	}
}
 